package com.yfbao.web.pdf.utils;

import cn.hutool.json.JSONUtil;
import com.itextpdf.text.BaseColor;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.*;
import com.yfbao.web.pdf.dto.ModificationDto;

import java.io.FileOutputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class PDFUtils {
    public static void modificationPdf(String sourcePath, String destPath, List<ModificationDto> editList) {
        PdfReader reader = null;
        PdfStamper stamper = null;

        try {
            reader = new PdfReader(sourcePath);
            stamper = new PdfStamper(reader, new FileOutputStream(destPath));

            // 重新设置所有权限
            stamper.setEncryption(
                    null, // 用户密码
                    null, // 所有者密码
                    PdfWriter.ALLOW_PRINTING |
                            PdfWriter.ALLOW_MODIFY_CONTENTS |
                            PdfWriter.ALLOW_COPY |
                            PdfWriter.ALLOW_MODIFY_ANNOTATIONS |
                            PdfWriter.ALLOW_FILL_IN |
                            PdfWriter.ALLOW_SCREENREADERS |
                            PdfWriter.ALLOW_ASSEMBLY,
                    PdfWriter.STANDARD_ENCRYPTION_128
            );

            // 按页码分组处理，提高效率
            Map<Integer, List<ModificationDto>> modificationsByPage = editList.stream()
                    .collect(Collectors.groupingBy(ModificationDto::getPage));

            // 处理每个页面的修改
            for (Map.Entry<Integer, List<ModificationDto>> entry : modificationsByPage.entrySet()) {
                int pageNum = entry.getKey();
                List<ModificationDto> pageModifications = entry.getValue();

                if (pageNum >= 1 && pageNum <= reader.getNumberOfPages()) {
                    editPdfContent(stamper, pageNum, pageModifications);
                }
            }

        } catch (Exception e) {
            System.err.println("PDF修改失败: " + e.getMessage());
            e.printStackTrace();
        } finally {
            // 确保资源关闭
            try {
                if (stamper != null) {
                    stamper.close();
                }
                if (reader != null) {
                    reader.close();
                }
            } catch (Exception e) {
                System.err.println("关闭资源时出错: " + e.getMessage());
            }
        }
    }

    private static void editPdfContent(PdfStamper stamper, int pageNum, List<ModificationDto> modifications) {
        try {
            PdfContentByte canvas = stamper.getOverContent(pageNum);

            for (ModificationDto mod : modifications) {
                applyModification(canvas, mod,stamper);
            }

        } catch (Exception e) {
            System.err.println("第" + pageNum + "页内容修改失败: " + e.getMessage());
            e.printStackTrace();
        }
    }

    private static void applyModification(PdfContentByte canvas, ModificationDto mod,PdfStamper stamper) {
        try {
            // 根据修改类型处理
            if ("text".equals(mod.getType())) {
                //选择区域上增加内容
//                applyTextModification(canvas, mod,stamper);
                //选择区域擦除后新增内容
                updateTextModification(canvas, mod,stamper);
            }
            // 可以扩展其他类型：image、rectangle等

        } catch (Exception e) {
            System.err.println("修改项处理失败(ID: " + mod.getId() + "): " + e.getMessage());
        }
    }

    /**
     * 在选择区域上面添加内容
     * @param canvas
     * @param mod
     * @param stamper
     */
    private static void applyTextModification(PdfContentByte canvas, ModificationDto mod,PdfStamper stamper) {
        try {
            canvas.saveState(); // 保存图形状态
            // 设置字体
            BaseFont baseFont = getBaseFont(mod.getFontFamily());
            canvas.setFontAndSize(baseFont, getFontSize(mod.getFontSize()));

            // 设置颜色
            setTextColor(canvas, mod.getFontColor());

            // 开始文本操作
            canvas.beginText();

            // 设置文本位置（PDF坐标系：左下角为原点）
            float x = mod.getX().floatValue();
            float y = getAdjustedYPosition(stamper.getReader(), mod.getPage(), mod.getY().floatValue());

            canvas.setTextMatrix(x, y);

            // 显示文本
            canvas.showText(mod.getNewText());

            canvas.endText();
            canvas.restoreState(); // 恢复图形状态

            System.out.println("成功应用文本修改: " + mod.getNewText() + " 在位置(" + x + ", " + y + ")");

        } catch (Exception e) {
            System.err.println("文本修改失败: " + e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * 将选择区域擦除(默认白色)，然后添加新内容
     * @param canvas
     * @param mod
     * @param stamper
     */
    private static void updateTextModification(PdfContentByte canvas, ModificationDto mod,PdfStamper stamper) {
        try {
            // 绘制白色矩形覆盖原内容
            canvas.setRGBColorFill(255, 255, 255); // 白色
            canvas.setColorFill(BaseColor.WHITE);
            Rectangle pageSize = stamper.getReader().getPageSize(1);
            float xStart = mod.getX().floatValue();
            float yStart = getAdjustedYPosition(stamper.getReader(), mod.getPage(), mod.getY().floatValue())- mod.getHeight().floatValue();

            canvas.rectangle(
                    xStart,
                    yStart,
                    mod.getWidth().floatValue(),
                    mod.getHeight().floatValue()
            );
            canvas.fill();


            canvas.saveState(); // 保存图形状态
            // 设置字体
            BaseFont baseFont = getBaseFont(mod.getFontFamily());
            canvas.setFontAndSize(baseFont, getFontSize(mod.getFontSize()));
            // 设置颜色
            setTextColor(canvas, mod.getFontColor());
            // 开始文本操作
            canvas.beginText();
            // 设置文本位置（PDF坐标系：左下角为原点）
            float x = mod.getX().floatValue();
            float y = getAdjustedYPosition(stamper.getReader(), mod.getPage(), mod.getY().floatValue())-getFontSize(mod.getFontSize());

            canvas.setTextMatrix(x, y);
            // 显示文本
            canvas.showText(mod.getNewText());
            canvas.endText();
            canvas.restoreState(); // 恢复图形状态

            System.out.println("成功应用文本修改:  在位置(" + x + ", " + y + ")");

        } catch (Exception e) {
            System.err.println("文本修改失败: " + e.getMessage());
            e.printStackTrace();
        }
    }

    // 辅助方法
    private static BaseFont getBaseFont(String fontFamily) throws Exception {
        // 根据字体名称映射到对应的BaseFont
        Map<String, String> fontMapping = new HashMap<>();
        fontMapping.put("宋体", "STSong-Light");
        fontMapping.put("黑体", "SimHei");
        fontMapping.put("微软雅黑", "MicrosoftYaHei");
        fontMapping.put("楷体", "KaiTi_GB2312");

        String baseFontName = fontMapping.getOrDefault(fontFamily, BaseFont.HELVETICA);

        // 尝试使用中文字体，如果失败则回退到默认字体
        try {
            return BaseFont.createFont(baseFontName + ",UniGB-UCS2-H", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
        } catch (Exception e) {
            return BaseFont.createFont(BaseFont.HELVETICA, BaseFont.WINANSI, BaseFont.EMBEDDED);
        }
    }

    private static float getFontSize(String fontSizeStr) {
        try {
            return Float.parseFloat(fontSizeStr);
        } catch (NumberFormatException e) {
            return 12f; // 默认字体大小
        }
    }

    private static void setTextColor(PdfContentByte canvas, String colorHex) {
        if (colorHex != null && colorHex.startsWith("#") && colorHex.length() == 7) {
            try {
                int r = Integer.parseInt(colorHex.substring(1, 3), 16);
                int g = Integer.parseInt(colorHex.substring(3, 5), 16);
                int b = Integer.parseInt(colorHex.substring(5, 7), 16);
                canvas.setRGBColorFill(r, g, b);
            } catch (Exception e) {
                canvas.setRGBColorFill(0, 0, 0); // 默认黑色
            }
        } else {
            canvas.setRGBColorFill(0, 0, 0); // 默认黑色
        }
    }

    private static float getAdjustedYPosition(PdfReader reader, int pageNum, float originalY) {
        try {
            // 获取页面大小，调整Y坐标（PDF坐标系与常规坐标系可能不同）
            Rectangle pageSize = reader.getPageSize(pageNum);
            return pageSize.getHeight() - originalY; // 转换为PDF坐标系
        } catch (Exception e) {
            return originalY;
        }
    }

    public static void main(String[] args) {
//        String msg = "[\n" +
//                "    {\n" +
//                "      \"id\": 1762226718797,\n" +
//                "      \"type\": \"text\",\n" +
//                "      \"page\": 1,\n" +
//                "      \"x\": 10,\n" +
//                "      \"y\": 51,\n" +
//                "      \"width\": 92,\n" +
//                "      \"height\": 24,\n" +
//                "      \"description\": \"第1页的文本替换修改\",\n" +
//                "      \"originalText\": \"\",\n" +
//                "      \"newText\": \"aaaaaaaaaaa\",\n" +
//                "      \"fontFamily\": \"宋体\",\n" +
//                "      \"fontSize\": \"12\",\n" +
//                "      \"fontColor\": \"#000000\"\n" +
//                "    },\n" +
//                "    {\n" +
//                "      \"id\": 1762226741802,\n" +
//                "      \"type\": \"text\",\n" +
//                "      \"page\": 1,\n" +
//                "      \"x\": 334,\n" +
//                "      \"y\": 64,\n" +
//                "      \"width\": 87,\n" +
//                "      \"height\": 21,\n" +
//                "      \"description\": \"第1页的文本替换修改\",\n" +
//                "      \"originalText\": \"\",\n" +
//                "      \"newText\": \"BBBBB\",\n" +
//                "      \"fontFamily\": \"宋体\",\n" +
//                "      \"fontSize\": \"12\",\n" +
//                "      \"fontColor\": \"#000000\"\n" +
//                "    },\n" +
//                "    {\n" +
//                "      \"id\": 1762227230590,\n" +
//                "      \"type\": \"text\",\n" +
//                "      \"page\": 1,\n" +
//                "      \"x\": 445,\n" +
//                "      \"y\": 581,\n" +
//                "      \"width\": 108,\n" +
//                "      \"height\": 39,\n" +
//                "      \"description\": \"第1页的文本替换修改\",\n" +
//                "      \"originalText\": \"12901\",\n" +
//                "      \"newText\": \"ccccc\",\n" +
//                "      \"fontFamily\": \"宋体\",\n" +
//                "      \"fontSize\": \"12\",\n" +
//                "      \"fontColor\": \"#000000\"\n" +
//                "    }\n" +
//                "  ]";

        String msg = "[\n" +
                "    {\n" +
                "      \"id\": 1762738232327,\n" +
                "      \"type\": \"text\",\n" +
                "      \"page\": 1,\n" +
                "      \"x\": 2,\n" +
                "      \"y\": 32,\n" +
                "      \"width\": 70,\n" +
                "      \"height\": 18,\n" +
                "      \"description\": \"第1页的文本替换修改\",\n" +
                "      \"originalText\": \"\",\n" +
                "      \"newText\": \"ZAAAA\",\n" +
                "      \"fontFamily\": \"宋体\",\n" +
                "      \"fontSize\": \"12\",\n" +
                "      \"fontColor\": \"#000000\"\n" +
                "    },\n" +
                "    {\n" +
                "      \"id\": 1762738242078,\n" +
                "      \"type\": \"text\",\n" +
                "      \"page\": 1,\n" +
                "      \"x\": 113,\n" +
                "      \"y\": 115,\n" +
                "      \"width\": 105,\n" +
                "      \"height\": 13,\n" +
                "      \"description\": \"第1页的文本替换修改\",\n" +
                "      \"originalText\": \"\",\n" +
                "      \"newText\": \"ABBBBB\",\n" +
                "      \"fontFamily\": \"宋体\",\n" +
                "      \"fontSize\": \"12\",\n" +
                "      \"fontColor\": \"#000000\"\n" +
                "    }\n" +
                "  ]";
        List<ModificationDto> editList = JSONUtil.toList(msg, ModificationDto.class);
//        List<ModificationDto> editList = Arrays.asList(
//                new ModificationDto(1762226718797L, "text", 1, 10.0, 51.0, 92.0, 24.0,
//                        "第1页的文本替换修改", "", "aaaaaaaaaaa", "宋体", "12", "#000000"),
//                new ModificationDto(1762226741802L, "text", 1, 334.0, 64.0, 87.0, 21.0,
//                        "第1页的文本替换修改", "", "BBBBB", "宋体", "12", "#000000")
//        );

        modificationPdf("D:\\下载\\bbb.pdf", "D:\\下载\\output.pdf", editList);
    }
}
